package com.lyc.speechtranscriber;

import android.annotation.SuppressLint;
import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioPlaybackCaptureConfiguration;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;

import com.lyc.speechtranscriber.bean.HdAudioSource;
import com.lyc.speechtranscriber.bean.MediaProjectionProvider;

public class HyperAudioRecord {
    private boolean mIsRecording = false;

    private AudioRecord microphoneRecord;
    private AudioRecord systemAudioRecord;

    @SuppressLint("MissingPermission")
    public HyperAudioRecord(HdAudioSource audioSource, MediaProjectionProvider mediaProjectionProvider){
        int sampleRate = 16000;
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
        int channelConfig = AudioFormat.CHANNEL_IN_MONO;
        int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat) * 2;

        boolean hasSystemAudioRecord = audioSource == HdAudioSource.ALL || audioSource == HdAudioSource.SYSTEM;
        boolean hasMicrophoneRecord = audioSource == HdAudioSource.ALL || audioSource == HdAudioSource.MIC;

        AudioFormat audioFormatObj = new AudioFormat.Builder()
                .setEncoding(audioFormat)
                .setSampleRate(sampleRate)
                .setChannelMask(channelConfig)
                .build();

        if (hasSystemAudioRecord && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q && mediaProjectionProvider != null){
            AudioPlaybackCaptureConfiguration.Builder captureBuilder = new AudioPlaybackCaptureConfiguration.Builder(mediaProjectionProvider.getMediaProjection());
            captureBuilder.addMatchingUsage(AudioAttributes.USAGE_MEDIA);//多媒体
            captureBuilder.addMatchingUsage(AudioAttributes.USAGE_ALARM);//闹铃
            captureBuilder.addMatchingUsage(AudioAttributes.USAGE_GAME);//游戏
            captureBuilder.addMatchingUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION);//未知
            captureBuilder.addMatchingUsage(AudioAttributes.USAGE_UNKNOWN);//未知
            AudioPlaybackCaptureConfiguration captureConfiguration = captureBuilder.build();

            AudioRecord.Builder recordBuilder = new AudioRecord.Builder()
                    .setAudioFormat(audioFormatObj)
                    .setBufferSizeInBytes(bufferSizeInBytes)
                    .setAudioPlaybackCaptureConfig(captureConfiguration);

            systemAudioRecord = recordBuilder.build();
        }

        if (hasMicrophoneRecord){
            /*microphoneRecord = new AudioRecord(
                    MediaRecorder.AudioSource.VOICE_COMMUNICATION,
                    sampleRate,
                    channelConfig,
                    audioFormat,
                    bufferSizeInBytes
            );*/

            microphoneRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate,
                    AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes);
        }

    }

    public void startRecording(){
        if (systemAudioRecord != null){
            systemAudioRecord.startRecording();
        }
        if (microphoneRecord != null) {
            microphoneRecord.startRecording();
        }
        mIsRecording = true;
    }

    public void stop(){
        if (systemAudioRecord != null){
            systemAudioRecord.stop();
        }
        if (microphoneRecord != null) {
            microphoneRecord.stop();
        }
        mIsRecording = false;
    }

    public void release(){
        if (systemAudioRecord != null){
            systemAudioRecord.release();
        }
        if (microphoneRecord != null) {
            microphoneRecord.release();
        }
        mIsRecording = false;
    }

    public int read(byte[] buffer, int sizeInBytes){
        byte[] buffer1 = null;
        byte[] buffer2 = null;
        int readBytes1 = 0;
        int readBytes2 = 0;

        if (microphoneRecord != null && microphoneRecord.getState() == AudioRecord.STATE_INITIALIZED){
            buffer1 = new byte[buffer.length];
            readBytes1 = microphoneRecord.read(buffer1,0, sizeInBytes);
        }

        if (systemAudioRecord != null && systemAudioRecord.getState() == AudioRecord.STATE_INITIALIZED){
            buffer2 = new byte[buffer.length];
            readBytes2 = systemAudioRecord.read(buffer2,0, sizeInBytes);
        }

        if (buffer1 != null && buffer2 != null){
            //麦克风音频数据提升音量
            for (int i = 0; i < buffer1.length; i++) {
                buffer1[i] = (byte) (buffer1[i] * 2);
            }

            //混音
            byte[] bytesMix = mix(buffer1, buffer2);
            System.arraycopy(bytesMix, 0, buffer, 0, bytesMix.length);

            return Math.max(readBytes1, readBytes2);
        }
        else if (buffer1 != null){
//                buffer.put(buffer1);
            System.arraycopy(buffer1, 0, buffer, 0, buffer1.length);
            return readBytes1;
        }
        else if (buffer2 != null){
//                buffer.put(buffer2);
            System.arraycopy(buffer2, 0, buffer, 0, buffer2.length);
            return readBytes2;
        }

        return 0;
    }

    private byte[] mix(byte[] bytes1, byte[] bytes2){
        byte[] bytesMix = new byte[bytes1.length];
        for (int i = 0; i < bytes1.length; i++) {
            bytesMix[i] = (byte) ((bytes1[i] + bytes2[i]) / 2);
        }
        return bytesMix;
    }

    public boolean isRecording() {
        return mIsRecording;
    }
}
